<?php

namespace PhpQq\WebQq;

use \PhpQq\WebQq\WebQqHelper;
use \PhpQq\WebQq\WebCurl;
use \PhpQq\WebQq\SavedSession;
use \PhpQq\WebQq\MessageQueue;
use \PhpQq\WebQq\MessageReceiver;
use \PhpQq\WebQq\MessageSender;
use \PhpQq\WebQq\Message;
use PhpQq\WebQq\FriendList;
use PhpQq\WebQq\WebQqConfig;
use PhpQq\WebQq\WebQqMessageExec;

/* * ***************************************************************************************
 * 模拟微信网页扫码登录代码 
 * ****************************************************************************************
 */

/**
 * 微信模拟登录
 * @email 397109515@qq.com
 * @author  seven
 */
class WebQq {

    /**
     * cookie文件地址
     * @var type 
     */
    private $cookie_file;

    /**
     * 存储登录成功后的数据
     * @var arr 
     */
    private $login_success_data;

    /**
     * 登录的用户信息
     * @var array 
     */
    private $user_data;

    /**
     * 好友列表
     * @var array 
     */
    private $friend;

    /**
     * 好友总数 好像群里的也算 
     * @var int
     */
    private $friend_num;

    /**
     * 群列表
     * @var arrya
     */
    private $group_list;
    private $curl;
    private $ptwebqq;
    private $webqq;
    private $psessionid;
    private $vfwebqq;
    private $hash;
    private $ptlogin;
    private $qrcookie;
    private $curlrs;
    private $qrcode;
    private $bkn;

    /**
     * 构造方法
     * @param string $cookie_path
     */
    public function __construct() {
        $this->curl = new \PhpQq\WebQq\WebCurl();
    }


    public function doPtLogin() {
        $this->curl->
                setUrl('https://ui.ptlogin2.qq.com/cgi-bin/login')->
                setGet([
                    'appid' => 501004106,
                    's_url' => 'http://w.qq.com/proxy.html',
                ])->exec();
        $cookie = $this->curl->getCookie();
        if (!isset($cookie['pt_user_id'])) {
            throw new \Exception('doPtLogin');
        }
        $this->ptlogin = $cookie;
    }
    
    /**
     * 保存登录的数据
     * @throws \Exception
     */
    public function saveCookie()
    {
        SavedSession::process($this->getLoginSession());
        SavedSession::save();
    }
    
    /**
     * 获取登录的二维码
     */
    public function doQRCode() {
        $this->loadtime = time();
        $qrpacket = $this->curl->
                setUrl('https://ssl.ptlogin2.qq.com/ptqrshow')->
                setGet([
                    'appid' => 501004106,
                    'e' => 2,
                    'l' => 'M',
                    's' => 1,
                    'd' => 72,
                    'v' => 4,
                ])->
                setCookie($this->ptlogin)->
                exec();
        $cookie = $this->curl->getCookie();
        if (!isset($cookie['qrsig'])) {
            throw new \Exception('doQRCode');
        }
        $this->qrcookie = $cookie;
        $this->curlrs = explode("\r\n\r\n", $qrpacket);
        $this->qrcode = end($this->curlrs);
    }

    
    public function checkQRCode() {
        $cookie = $this->qrcookie + $this->ptlogin;
        $get = [
            'ptqrtoken' => $this->hash33($this->qrcookie['qrsig']),
            'webqq_type' => 10,
            'remember_uin' => 1,
            'login2qq' => 1,
            'aid' => 501004106,
            'u1' => 'http://w.qq.com/proxy.html?login2qq=1&webqq_type=10',
            'ptredirect' => 0,
            'ptlang' => 2052,
            'daid' => 164,
            'from_ui' => 1,
            'pttype' => 1,
            'dumy' => '',
            'fp' => 'loginerroralert',
            'action' => "0-0-" . (string) ((time() - $this->loadtime) * 1000 + mt_rand(1, 99)),
            'mibao_css' => 'm_webqq',
            't' => 1,
            'g' => 1,
            'js_type' => 0,
            'js_ver' => 10194,
            'login_sig' => '',
            'pt_randsalt' => 2
        ];
        $result = $this->curl->
                setUrl('https://ssl.ptlogin2.qq.com/ptqrlogin')->
                setGet($get)->
                setCookie($cookie)->
                setTimeout(10)->
                exec();
        if (!preg_match('/ptuiCB\(\'(.*)\',\'(.*)\',\'(.*)\'/iU', $result, $status)) {
            throw new \Exception('checkQRCode::preg_match');
        }
        $cookie = $this->curl->getCookie();
        if ($status[1] == 0 && !isset($cookie['ptwebqq'])) {
            throw new \Exception('checkQRCode::getCookie');
        }
        $this->ptwebqq = $cookie;
        return [$status[1], $status[3]];
    }

    public function doWebQQLogin($url) {
        $this->curl->
                setUrl($url)->
                exec();
        $cookie = $this->curl->getCookie();
        if (!isset($cookie['p_skey'])) {
            throw new \Exception('doWebQQLogin');
        }
        $this->webqq = $cookie;
    }

    public function doPSessionId() {
        $json = $this->curl->
                setUrl('http://d1.web2.qq.com/channel/login2')->
                setReferer('http://d1.web2.qq.com/proxy.html?v=20151105001')->
                setPost([
                    'r' => json_encode([
                        'ptwebqq' => $this->ptwebqq['ptwebqq'],
                        'clientid' => 53999199,
                        'psessionid' => '',
                        'status' => 'online',
                            ], JSON_FORCE_OBJECT)
                ])->
                setCookie($this->ptwebqq + $this->webqq)->
                returnHeader(false)->
                exec();
        $data = json_decode($json, true);
        if (!isset($data['result']['psessionid'])) {
            throw new \Exception('doPSessionId');
        }
        $this->psessionid = $data['result'];
    }

    public function doVFWebqq() {
        $json = $this->curl->
                setUrl('http://s.web2.qq.com/api/getvfwebqq')->
                setReferer('http://s.web2.qq.com/proxy.html?v=20130916001')->
                setGet([
                    'ptwebqq' => $this->ptwebqq['ptwebqq'],
                    'clientid' => 53999199,
                    'psessionid' => '',
                ])->
                setCookie($this->ptwebqq + $this->webqq)->
                returnHeader(false)->
                exec();
        $data = json_decode($json, true);

        if (!isset($data['result']['vfwebqq'])) {
            $this->doVFWebqq();
            return false;
        }
        $this->vfwebqq = $data['result'];
    }

    public function hash33($qrsig) {
        for ($e = 0, $i = 0, $n = strlen($qrsig); $n > $i; $i++) {
            $e += (($e << 5) + ord($qrsig[$i])) & 0xFFFFFFFF;
        }
        return 2147483647 & $e;
    }

    public function doHash() {
        $selfUin = trim($this->webqq['uin'], 'o');
        $ptwebqq = $this->ptwebqq['ptwebqq'];
        $n = [0, 0, 0, 0];
        for ($t = 0; $t < strlen($ptwebqq); $t++) {
            $n[$t % 4] = $n[$t % 4] ^ ord($ptwebqq[$t]);
        }
        $u = ['EC', 'OK'];
        $v = [];
        $v[0] = $selfUin >> 24 & 255 ^ ord($u[0][0]);
        $v[1] = $selfUin >> 16 & 255 ^ ord($u[0][1]);
        $v[2] = $selfUin >> 8 & 255 ^ ord($u[1][0]);
        $v[3] = $selfUin & 255 ^ ord($u[1][1]);
        $ui = [];
        for ($t = 0; $t < 8; $t++) {
            $ui[$t] = ($t % 2 == 0) ? $n[$t >> 1] : $v[$t >> 1];
        }
        $hex = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
        $hash = '';
        for ($t = 0; $t < count($ui); $t++) {
            $hash .= $hex[$ui[$t] >> 4 & 15];
            $hash .= $hex[$ui[$t] & 15];
        }
        $this->hash = ['hash' => $hash];
    }

    public function doBkn() {
        $skey = $this->webqq['skey'];
        $lenth = strlen($skey);
        $result = 5381;
        for ($n = 0; $n < $lenth; $n++) {
            $result += ($result << 5) + ord(substr($skey, $n, 1));
        }
        $bkn = 2147483647 & $result;
        $this->bkn = ['bkn' => $bkn];
    }

    /**
     * 获得登录的用户cookie信息  
     * @return type
     */
    public function getLoginSession() {
        $info = array_merge($this->ptwebqq, $this->webqq, $this->psessionid, $this->vfwebqq, $this->hash, $this->bkn);
        $info['uin'] = $this->ptwebqq['uin'];
        return $info;
    }

    public function getQRCode() {
        return $this->qrcode;
    }
    
    /**
     * 把二维码转换成字符串 方便输出到终端
     * @param type $code
     */
    public function displayQRCode($code){
            echo PHP_EOL . PHP_EOL;
            $image = imagecreatefromstring($code);
            for($y = 0; $y < imagesy($image); $y = $y + 1){
                    $log = "";
                    for($x = 0; $x < imagesx($image); $x = $x + 1){
                            $rgb = imagecolorat($image, $x, $y);
                            $log .= $rgb != 0 ? chr(220) . chr(220) : "  ";
                    }
                    echo $log . PHP_EOL;
            }
            echo PHP_EOL . PHP_EOL;
    }
    
    /**
     * 获得个人信息
     * @return type
     */
    public function getSelfInfo(){
        $json = $this->curl->
	    setUrl('http://s.web2.qq.com/api/get_self_info2')->
	    setReferer('http://s.web2.qq.com/proxy.html?v=20130916001')->
	    setCookie(SavedSession::$cookie)->
	    returnHeader(false)->
	    setTimeOut(5)->
	    exec();
	    $json = json_decode($json, true);
        if($json['retcode'] == 0)
        {
            FriendList::getInstance()->setLoginUserInfo($json['result']);
            return $json;
        }
        else
        {
            return false;
        }
        
    }
    
    /**
     * 最近联系过的用户
     * @return type
     */
    public function getRecentList(){
        $json = $this->curl->
	    setUrl('http://d1.web2.qq.com/channel/get_recent_list2')->
	    setReferer('http://d1.web2.qq.com/proxy.html?v=20151105001')->
        setPost([
            'r' => json_encode([
                'vfwebqq' => SavedSession::$vfwebqq,
                'clientid' => SavedSession::$clientid,
                'psessionid' => SavedSession::$psessionid,
            ], JSON_FORCE_OBJECT)
        ])->
	    setCookie(SavedSession::$cookie)->
	    returnHeader(false)->
	    setTimeOut(5)->
	    exec();
	    $json = json_decode($json, true);
        return $json;
    }

    public function getOnlineBuddies(){
        $json = $this->curl->
        setUrl('http://d1.web2.qq.com/channel/get_online_buddies2')->
        setReferer('http://d1.web2.qq.com/proxy.html?v=20151105001')->
        setGet([
            'vfwebqq' => SavedSession::$vfwebqq,
            'clientid' => SavedSession::$clientid,
            'psessionid' => SavedSession::$psessionid,
        ])->
	    setCookie(SavedSession::$cookie)->
	    returnHeader(false)->
	    setTimeOut(5)->
	    exec();
	    $json = json_decode($json, true);
        return $json;
    }

    public function uin2acc($uin){
        $json = $this->curl->
        setUrl('http://s.web2.qq.com/api/get_friend_uin2')->
        setReferer('http://s.web2.qq.com/proxy.html?v=20130916001')->
        setGet([
            'tuin' => $uin,
            'vfwebqq' => SavedSession::$vfwebqq,
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $json = json_decode($json, true);
        return $json['result']['account'];
    }

    /**
     * 获得好友昵称
     * @param type $uin
     * @return boolean
     */
    public function getFriendNick($uin){
        $json = $this->curl->
        setUrl('http://s.web2.qq.com/api/get_friend_info2')->
        setReferer('http://s.web2.qq.com/proxy.html?v=20130916001')->
        setGet([
            'tuin' => $uin,
            'vfwebqq' => SavedSession::$vfwebqq,
            'clientid' => SavedSession::$clientid,
            'psessionid' => SavedSession::$psessionid,
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $json = json_decode($json, true);
        if(isset($json['result']['nick'])){
            return $json['result']['nick'];
        }else{
            return false;
        }
    }

    public function banGroupMember($gc, $member, $time){
        $json = $this->curl->
        setUrl('http://qinfo.clt.qq.com/cgi-bin/qun_info/set_group_shutup')->
        setReferer('http://qinfo.clt.qq.com/qinfo_v3/member.html')->
        setPost([
            'gc' => $gc,
            'shutup_list' => "[{\"t\":$time,\"uin\":$member}]",
            'bkn' => SavedSession::$bkn
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $data = json_decode($json, true);
        if(isset($data['ec']) && $data['ec'] == 0){
            return true;
        }
        return false;
    }

    public function changeGroupCard($gc, $member, $card){
        $json = $this->curl->
        setUrl('http://qun.qq.com/cgi-bin/qun_mgr/set_group_card')->
        setReferer('http://qun.qq.com/member.html')->
        setPost([
            'gc' => $gc,
            'u' => $member,
            'name' => $card,
            'bkn' => SavedSession::$bkn
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $data = json_decode($json, true);
        if(isset($data['ec']) && $data['ec'] == 0){
            return true;
        }
        return false;
    }

    public function getGroupList(){
        $list1 = self::getGroupListbyWebQQ();
        if($list1 === false){
            return false;
        }
        $list2 = self::getGroupListbyWebQun();
        foreach($list1 as $key => $group){
            if(isset($list2[$list1[$key]['name']])){
                $list1[$key] = array_merge($list1[$key], $list2[$list1[$key]['name']]);
            }
        }
        FriendList::getInstance()->setGroup($list1);
        return $list1;
    }

    private function getGroupListbyWebQQ(){
        $json = $this->curl->
        setUrl('http://s.web2.qq.com/api/get_group_name_list_mask2')->
        setReferer('http://d1.web2.qq.com/proxy.html?v=20130916001')->
        setPost([
            'r' => json_encode([
                'vfwebqq' => SavedSession::$vfwebqq,
                'hash' => SavedSession::$hash,
            ], JSON_FORCE_OBJECT)
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $json = json_decode($json, true);
        $map = [];
        if(!isset($json['result']['gnamelist']) || !is_array($json['result']['gnamelist'])){
            $this->error = '获得群列表失败';
            return false;
        }
        foreach($json['result']['gnamelist'] as $namelist){
            $map[$namelist['gid']] = [
                'gid' => $namelist['code'],
                'name' => str_replace("\xc2\xa0", ' ', $namelist['name']),
            ];
        }
        return $map;
    }

    private function getGroupListbyWebQun(){
        $json = $this->curl->
        setUrl('http://qun.qq.com/cgi-bin/qun_mgr/get_group_list')->
        setReferer('http://qun.qq.com/member.html')->
        setPost([
            'bkn' => SavedSession::$bkn
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $data = json_decode($json, true);
        $return = [];
        foreach($data as $permission => $list){
            if(is_array($list)){
                foreach($list as $group){
                    $return[html_entity_decode(str_replace('&nbsp;', ' ', $group['gn']))] = [
                        'permission' => $permission,
                        'number' => $group['gc'],
                        'owner' => $group['owner']
                    ];
                }
            }
        }
        return $return;
    }

    /**
     * 获得群成员列表
     * @param type $gid
     * @return boolean
     */
    public function getGroupMemberList($gid){
        $json = $this->curl->
        setUrl('http://s.web2.qq.com/api/get_group_info_ext2')->
        setReferer('http://s.web2.qq.com/proxy.html?v=20130916001')->
        setGet([
            'gcode' => $gid,
            'vfwebqq' => SavedSession::$vfwebqq
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $json = json_decode($json, true);
		if(!isset($json['result']) || !is_array($json['result']['minfo'])){
            return false;
        }
        $nick = [];
        foreach($json['result']['minfo'] as $member){
            $nick[$member['uin']] = str_replace("\xE2\x80\xAE", '', $member['nick']);
        }
        
        if(isset($json['result']['cards'])){
            foreach($json['result']['cards'] as $member){
                $nick[$member['muin']] = str_replace("\xE2\x80\xAE", '', $member['card']);
            }
        }
        return $nick;
    }
    
    /**
     * 获得群列表
     * @return array
     */
    public function getFriendList(){
        $json = $this->curl->
        setUrl('http://s.web2.qq.com/api/get_user_friends2')->
        setReferer('http://s.web2.qq.com/proxy.html?v=20130916001')->
        setPost([
            'r' => json_encode([
                'vfwebqq' => SavedSession::$vfwebqq,
                'hash' => SavedSession::$hash
            ])
        ])->
        setCookie(SavedSession::$cookie)->
        returnHeader(false)->
        setTimeOut(5)->
        exec();
        $data = json_decode($json, true);
        $rs = [];
        if(isset($data['result']['friends'])){
            foreach($data['result']['friends'] as $key => $d){
                $rs[$d['uin']] = [
                    'uid'=>'uid:'.$d['uin'],
                    'nick' => $data['result']['info'][$key]['nick'],
                    'mark' => $data['result']['info'][$key]['nick'],
                    'categorie' => $d['categories'] == 0 ? 'default' : $data['result']['categories'][$d['categories'] - 1]['name'],
                    'flag' => $d['flag'],
                ];
            }
            foreach($data['result']['marknames'] as $m){
                $rs[$m['uin']]['mark'] = $m['markname'];
            }
            foreach($data['result']['vipinfo'] as $m){
                $rs[$m['u']]['vip_level'] = $m['vip_level'];
                $rs[$m['u']]['is_vip'] = $m['is_vip'];
            }
        }
        else
        {
            return false;
        }
        FriendList::getInstance()->setFriend($rs);
        return $rs;
    }

    public function getLoginUserName()
    {
        return str_replace(['o0','o'], '', SavedSession::$uin);
    }
    
    public function sender()
    {
        return new MessageSender();
    }
    
    public function receiver()
    {
        return new MessageReceiver();
    }
    
    /**
     * 获得好友列表
     * @return array
     */
    public function getFriend() {
        return  FriendList::getInstance()->getFriend();
    }

    /**
     * 获得群列表
     * @return array
     */
    public function getGroup() {
        return  FriendList::getInstance()->getGroup();
    }
    
    /**
     * 返回登录用户的信息
     * @return array
     */
    public function getLoginUserInfo() {
        return  FriendList::getInstance()->getLoginUserInfo();
    }
}
